<template>
  <div id="flowChart">
    <div class="btn-init">
      <div class="btn" @click="addCircle" title="起始节点">
        <img src="./imgs/circle.svg" />
      </div>
      <div class="btn" @click="addRect" title="常规节点">
        <img src="./imgs/rect.svg" />
      </div>
      <div class="btn" @click="addRhombus" title="条件节点">
        <img src="./imgs/rhombus.svg" />
      </div>
    </div>
    <div class="operating">
      <div class="btn-group">
        <div class="btn" @click="addLine" title="直线">
          <span class="icon-zhixian"></span>
        </div>
        <div class="btn" @click="addSmooth" title="曲线">
          <span class="icon-quxian"></span>
        </div>
        <div class="btn" @click="addArrowLine" title="箭头直线">
          <span class="icon-jiantouzhixian"></span>
        </div>
        <div class="btn" @click="addArrowSmooth" title="箭头曲线">
          <span class="icon-jiantouquxian"></span>
        </div>
      </div>
      <div class="btn-group">
        <div class="btn" @click="changeMode('edit')" title="选择模式">
          <span class="icon-chose"></span>
        </div>
        <div class="btn" @click="changeMode('drag')" title="拖拽模式">
          <span class="icon-move"></span>
        </div>
      </div>
      <div class="btn-group">
        <div
          class="btn"
          @click="del"
          style="margin-top: 5px;"
          title="删除"
        >
          <span class="icon-shanchu"></span>
        </div>
        <div class="btn" @click="save" title="保存">
          <span class="icon-baocun"></span>
        </div>
      </div>
      <div class="btn-group input">
        <el-input size="mini" v-model="workflowName" placeholder="请输入流图名称..."></el-input>
      </div>
      <p class="tip btn-group">tip：先点击左侧图标，再点击需要放置的地方哦～</p>
    </div>
    <div class="info">
      <div class="title">
        <span>{{ infoTitle }}属性</span>
      </div>
      <div class="content">
        <el-checkbox v-if="isBlank === true" v-model="checked">网格对齐</el-checkbox>
        <el-form v-else label-position="left" label-width="60px">
          <el-form-item v-if="isNode !== true" label="文本" ref="textInput">
            <el-input size="mini" v-model="text"></el-input>
          </el-form-item>
          <el-form-item v-if="isNode !== true" label="动作">
            <el-select
              v-model="action"
              size="mini"
              filterable
              placeholder="绑定动作"
              value
            >
              <el-option
                v-for="item in actionList"
                :key="item.id"
                :label="item.label"
                :value="item.id"
              ></el-option>
            </el-select>
          </el-form-item>
          <!-- 线-->
          <el-form-item v-if="isNode === true" label="名称" ref="inputFocus">
            <el-input size="mini" v-model="name"></el-input>
          </el-form-item>
          <el-form-item v-if="isNode === true" label="功能">
            <el-select
              v-model="func"
              size="mini"
              filterable
              placeholder="绑定功能"
              value
            >
              <el-option
                v-for="item in funcList"
                :key="item.id"
                :label="item.label"
                :value="item.id"
              ></el-option>
            </el-select>
          </el-form-item>
          <el-form-item v-if="isNode === true" label="账号">
            <el-select
              v-model="account"
              size="mini"
              filterable
              multiple
              collapse-tags
              placeholder="绑定账号"
              value
            >
              <el-option
                v-for="item in accountList"
                :key="item.id"
                :label="item.label"
                :value="item.id"
              ></el-option>
            </el-select>
          </el-form-item>
          <el-form-item v-if="isNode === true" label="流图">
            <el-select
              v-model="workflow"
              size="mini"
              filterable
              clearable
              placeholder="绑定流图"
              value
            >
              <el-option
                v-for="item in workflowList"
                :key="item.id"
                :label="item.label"
                :value="item.id"
              ></el-option>
            </el-select>
          </el-form-item>
          <el-form-item v-if="isNode === true" label="类型">
            <el-select
              v-model="nodeType"
              size="mini"
              filterable
              placeholder="请选择类型"
              value
            >
              <el-option
                v-for="item in nodeTypeList"
                :key="item.id"
                :label="item.label"
                :value="item.id"
              ></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="颜色">
            <el-color-picker v-model="color"></el-color-picker>
          </el-form-item>
        </el-form>
      </div>
    </div>
  </div>
</template>

<script>
(() => {
  const script = document.createElement('script')
  script.src = '//gw.alipayobjects.com/os/antv/assets/g6/1.2.8/g6.min.js'
  const s = document.getElementsByTagName('script')[0]
  s.parentNode.insertBefore(script, s)
})()

export default {
  name: 'Flowchart',
  props: {
    actionList: {
      type: Array, default: () => []
    },
    funcList: { // 功能下拉框
      type: Array, default: () => []
    },
    accountList: { // 账号下拉框
      type: Array, default: () => []
    },
    workflowList: { // 流图下拉框
      type: Array, default: () => []
    },
    nodeTypeList: { // 类型下拉框
      type: Array,
      default: () => [
        {
          id: 0,
          label: '普通节点'
        },
        {
          id: 1,
          label: '起始节点'
        },
        {
          id: 2,
          label: '条件节点'
        }
      ]
    }
  },
  data () {
    return {
      action: '',
      name: '',
      text: '',
      func: '', // 功能
      account: '', // 账号
      workflow: '', // 流图
      nodeType: 0, // 类型：普通节点
      color: '',

      net: '',
      Util: '',
      workflowName: '',
      activation: '', // 当前激活的节点
      isNode: false, // 当前是节点
      isBlank: true, // 当前是空白区
      checked: true, // 网格对齐
      infoTitle: '画布', // 属性标题
      oldColor: '', // 获取节点本身颜色
      type: '' // 有值为编辑状态
    }
  },
  watch: {
    /**
     * 监听输入框
     */
    action: function () {
      this.update()
    },
    name: function () {
      this.update()
    },
    text: function () {
      this.update()
    },
    func: function () {
      this.update()
    },
    account: function () {
      this.update()
    },
    workflow: function () {
      this.update()
    },
    nodeType: function () {
      this.update()
    },
    color: function () {
      this.update()
    },
    /**
     * 网格切换
     */
    checked: function () {
      const _saveData = this.net.save()
      this.net.destroy() // 销毁画布
      this.initG6()
      this.net.read(_saveData)
      this.net.render()
    }
  },
  mounted () {
    this.$nextTick(() => {
      if (window.G6) {
        this.initG6()
      } else {
        setTimeout(() => {
          this.initG6()
        }, 100)
      }
    })
  },
  methods: {
    initG6 () {
      const self = this
      self.Util = G6.Util
      let grid
      if (self.checked) {
        grid = {
          forceAlign: true, // 是否支持网格对齐
          cell: 25 // 网格大小
        }
      } else {
        grid = null
      }
      self.net = new G6.Net({
        id: 'flowChart', // 容器ID
        mode: 'edit',
        grid: grid,
        height: 700 // 画布高
      })
      /**
       *点击空白处
        */
      self.net.on('click', (ev) => {
        if (!self.Util.isNull(ev.item)) {
          self.isBlank = false
        } else {
          self.isBlank = true
          self.infoTitle = '画布'
        }
      })
      /**
       *点击节点
        */
      self.net.on('itemclick', function (ev) {
        self.isNode = self.Util.isNode(ev.item) // 是否为Node
        self.activation = ev.item
        if (self.isNode) {
          /* 激活节点后节点名称input聚焦 */
          self.$nextTick(() => {
            self.$refs.inputFocus.$el.querySelector('input').focus()
          })
          self.infoTitle = '节点'
          self.name = ev.item.get('model').label
          self.func = ev.item.get('model').func
          self.account = ev.item.get('model').account || []
          self.workflow = ev.item.get('model').workflow
          self.nodeType = ev.item.get('model').nodeType
        } else {
          self.$nextTick(() => {
            self.$refs.textInput.$el.querySelector('input').focus()
          })
          self.infoTitle = '边'
          self.text = ev.item.get('model').label
          self.action = ev.item.get('model').action
        }
        self.color = self.oldColor
      })
      /**
       * 鼠标移入移出事件改变颜色
       */
      self.net.on('itemmouseenter', ev => {
        const item = ev.item
        self.oldColor = item.get('model').color // 获取节点颜色
        self.net.update(item, {
          color: '#108EE9'
        })
        self.net.refresh()
      })
      self.net.on('itemmouseleave', ev => {
        const item = ev.item
        self.net.update(item, {
          color: self.oldColor
        })
        self.net.refresh()
      })
      /**
       * 提示信息
       */
      self.net.tooltip(true)
      self.net.edge().tooltip((obj) => {
        return [
          ['label', obj.label || 'null'],
          ['color', obj.color]
        ]
      })
      self.net.node().tooltip((obj) => {
        return [
          ['label', obj.label],
          ['color', obj.color]
        ]
      })
      /**
       * 渲染
       */
      self.net.render()
    },
    addCircle () {
      this.net.beginAdd('node', {
        shape: 'circle',
        nodeType: 1,
        label: 'Start',
        color: '#ff9d00',
        size: [74, 74]
      })
    }, // 添加起始节点
    addRect () {
      this.net.beginAdd('node', {
        shape: 'rect',
        nodeType: 0,
        label: 'Normal',
        color: '#0084ff',
        size: [82, 50]
      })
    }, // 添加常规节点
    addRhombus () {
      this.net.beginAdd('node', {
        shape: 'rhombus',
        nodeType: 2,
        label: 'Decision',
        color: '#00f7ff',
        size: [84, 80]
      })
    }, // 添加条件节点
    addLine () {
      this.net.beginAdd('edge', {
        shape: 'line'
      })
    }, // 添加直线
    addSmooth () {
      this.net.beginAdd('edge', {
        shape: 'smooth'
      })
    }, // 添加曲线
    addArrowSmooth () {
      this.net.beginAdd('edge', {
        shape: 'smoothArrow'
      })
    }, // 添加箭头曲线
    addArrowLine () {
      this.net.beginAdd('edge', {
        shape: 'arrow'
      })
    }, // 添加箭头直线
    changeMode (mode) {
      this.net.changeMode(mode)
    }, // 拖拽与编辑模式的切换
    del () {
      this.net.del()
    }, // 删除
    save () {
      /* 验证流图名称 */
      if (this.workflowName !== '') {
        const data = this.net.save()
        if (data.source.nodes.length === 0) {
          this.$message({ type: 'error', message: '流图内容不能为空' })
          return false
        }
        /* 验证节点名称 */
        for (const item of data.source.nodes) {
          if (item.label === '' || item.label === null || item.label === undefined) {
            this.$message({ type: 'error', message: '节点名称不能为空' })
            return false
          }
        }
        data.source.name = this.workflowName
        this.$emit('saveData', data.source, this.type)
      } else {
        this.$message({ type: 'error', message: '流图名称不能为空' })
      }
    }, // 保存
    update () {
      if (this.activation.get('type') === 'node') {
        this.net.update(this.activation, {
          label: this.name,
          func: this.func,
          account: this.account,
          workflow: this.workflow,
          nodeType: this.nodeType,
          color: this.color
        })
      } else {
        this.net.update(this.activation, {
          label: this.text,
          color: this.color,
          action: this.action
        })
      }
    }, // 更新节点
    clearView () {
      this.type = ''
      this.workflowName = ''
      this.net.changeData()
    }, // 清空视图
    source (nodes, edges, name, type) {
      this.type = type
      this.workflowName = name
      this.net.changeData(nodes, edges)
    } // 更新数据
  }
}
</script>

<style lang="less" scoped>
@import url('./font.less');

#flowChart {
  position: relative;
  overflow: hidden;
  border: 1px solid #ebeef5;
}

.btn-init {
  position: absolute;
  top: 40px;
  left: 0;
  z-index: 8;
  height: 500px;
  padding: 0 20px;
  background-color: #fff;
  box-shadow: 1px 1px 4px 0 #0a0a0a2e;

  .btn {
    margin: 20px 0;
  }
}

.operating {
  position: absolute;
  z-index: 8;
  padding: 0 10px;
  background-color: #fff;
  box-shadow: 1px 1px 4px 0 #0a0a0a2e;
}

.info {
  position: absolute;
  right: 0;
  z-index: 8;
  box-shadow: 1px 1px 4px 0 #0a0a0a2e;

  .title {
    height: 40px;
    padding-left: 10px;
    line-height: 40px;
    background: rgb(235, 238, 242);
    border-top: 1px solid #dce3e8;
    border-bottom: 1px solid #dce3e8;
    border-left: 1px solid #dce3e8;

    span {
      font-size: 14px;
    }
  }

  .content {
    width: 200px;
    height: 500px;
    padding: 10px;
    background: rgba(247, 249, 251, 0.45);
    border-left: 1px solid #e6e9ed;
  }
}

.btn-group {
  display: inline-block;
  padding-right: 14px;
  padding-left: 10px;
  border-right: 1px solid #efefef;

  &.input {
    transform: translateY(-2px);
  }

  &.tip {
    font-size: 12px;
    color: #767a85;
  }

  &:last-of-type {
    border-right: 0;
  }

  .btn {
    display: inline-block;
    width: 30px;
    height: 30px;
    margin: 2px;
    line-height: 30px;
    text-align: center;
    cursor: pointer;
    border: 1px solid rgba(233, 233, 233, 0);

    i {
      font-size: 20px;
    }

    &:hover {
      color: #767a85;
      background: #fafafe;
      border: 1px solid #e9e9e9;
      border-radius: 2px;
    }
  }

  .el-form-item {
    margin-bottom: 0 !important;
  }
}
</style>
